package me.sdevil507.org.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import me.sdevil507.biz.common.exceptions.PhoneNumberExistedException;
import me.sdevil507.org.dto.OrgExpertInfoParamsDto;
import me.sdevil507.org.dto.OrgUserParamsDto;
import me.sdevil507.org.events.OrgUserLastLoginTimeEvent;
import me.sdevil507.org.mapper.OrgUserMapper;
import me.sdevil507.org.po.*;
import me.sdevil507.org.repository.*;
import me.sdevil507.org.service.OrgDeptService;
import me.sdevil507.org.service.OrgUserService;
import me.sdevil507.supports.helper.Md5PasswordHelper;
import me.sdevil507.supports.jpa.PageParamsDTO;
import me.sdevil507.supports.jpa.SortParamsDTO;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.shiro.realm.OrgSmsRealm;
import me.sdevil507.supports.shiro.realm.OrgUsernamePasswordRealm;
import me.sdevil507.supports.util.AESUtil;
import me.sdevil507.supports.util.RegularExpressionUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * ApiUserServiceImpl
 *
 * @author sdevil507
 * created on 2019/12/15
 */
@Service
@Slf4j
public class OrgUserServiceImpl implements OrgUserService {

    @Autowired
    OrgDeptService orgDeptService;

    @Autowired
    private OrgUserRepository orgUserRepository;

    @Autowired
    private OrgUsernamePasswordRealm orgUsernamePasswordRealm;

    @Autowired
    private OrgSmsRealm orgSmsRealm;

    @Autowired
    private OrgUserMapper orgUserMapper;

    @Autowired
    private OrgRepository orgRepository;

    @Autowired
    private OrgDeptRepository orgDeptRepository;

    @Autowired
    private OrgUserRelRepository orgUserRelRepository;

    @Autowired
    private Md5PasswordHelper md5PasswordHelper;

    @Autowired
    private OrgRoleRepository orgRoleRepository;

    @Autowired
    private OrgExpertInfoRepository orgExpertInfoRepository;

    @Autowired
    JPAQueryFactory jpaQueryFactory;

    @Override
    public OrgUserPo readOneByPhoneNumber(String phoneNumber) {
        return orgUserRepository.findByPhoneNumberAndDeletedIsFalse(phoneNumber);
    }

    @Override
    public OrgUserPo readOneByMail(String mail) {
        return orgUserRepository.findByMailAndDeletedIsFalse(mail);
    }

    @Override
    public OrgUserPo readOneById(Long id) {
        return orgUserRepository.findById(id).orElse(null);
    }

    @Override
    public boolean existsByPhoneNumber(String phoneNumber) {
        return orgUserRepository.existsByPhoneNumberAndDeletedIsFalse(phoneNumber);
    }

    @Override
    public void updatePasswordByPhoneNumber(String newPassword, String phoneNumber) {
        orgUserRepository.updatePasswordByPhoneNumber(newPassword, phoneNumber);
        orgUsernamePasswordRealm.clearCachedAuthenticationInfo(phoneNumber);
    }

    @Override
    @EventListener
    @Async
    public void updateLastLoginTime(OrgUserLastLoginTimeEvent event) {
        try {
            OrgUserPo userPo = orgUserRepository.findByPhoneNumberAndDeletedIsFalse(event.getPhoneNumber());

            Date date = event.getDate();
            Instant instant = date.toInstant();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
            userPo.setLastLoginTime(localDateTime);
            orgUserRepository.save(userPo);
        } catch (Exception e) {
            log.error("更新用户最后登录时间失败:", e);
        }
    }

    @Override
    public void updateData(OrgUserPo orgUserPo) {
        orgUserRepository.save(orgUserPo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(OrgUserParamsDto dto) {
        long id = dto.getId();
        // 当前操作用户的机构
        Long orgId = OrgAccountHelper.getOrgId();
        if(!ObjectUtil.isEmpty(dto.getDeptId())){
            orgId = dto.getDeptId();
        }
        if(orgId != null){
            QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
            // 移除用户下的关联关系
            OrgUserPo orgUserPo = orgUserRepository.findById(id).orElse(null);
            Predicate predicate;
            if (orgUserPo != null) {
                // 1.移除用户下该机构下的部门
                QOrgDeptPo qOrgDeptPo = QOrgDeptPo.orgDeptPo;
                predicate = qOrgDeptPo.id.isNotNull()
                        .and(qOrgDeptPo.users.any().id.eq(id))
                        .and(qOrgDeptPo.id.eq(orgId));
                ArrayList<OrgDeptPo> orgDeptPos = Lists.newArrayList(orgDeptRepository.findAll(predicate));
                if (!orgDeptPos.isEmpty()) {
                    orgUserPo.getDepts().removeAll(orgDeptPos);
                }
                // 2.移除用户下该机构下的角色
                QOrgRolePo qOrgRolePo = QOrgRolePo.orgRolePo;
                predicate = qOrgRolePo.id.isNotNull()
                        .and(qOrgRolePo.users.any().id.eq(id))
                        .and(qOrgRolePo.deptId.eq(orgId));
                ArrayList<OrgRolePo> orgRolePos = Lists.newArrayList(orgRoleRepository.findAll(predicate));
                if (!orgRolePos.isEmpty()) {
                    orgUserPo.getRoles().removeAll(orgRolePos);
                }
                orgUserRepository.save(orgUserPo);
            }

            // 判断该id是否只在一个机构
//        predicate = qOrgUserRelPo.id.isNotNull()
//                .and(qOrgUserRelPo.user.id.eq(id));
//        long count = orgUserRelRepository.count(predicate);
//        if (count <= 1) {
//            // 如果用户在一个机构中分配,执行逻辑删除
//            orgUserRepository.logicDelete(id);
//        }

            // 更新用户机构关系
            predicate = qOrgUserRelPo.id.isNotNull().and(qOrgUserRelPo.org.id.eq(orgId)).and(qOrgUserRelPo.user.id.eq(id));
            OrgUserRelPo orgUserRelPo = orgUserRelRepository.findOne(predicate).orElse(null);
            if(orgUserRelPo != null){
                orgUserRelPo.setMgr(false);
                orgUserRelRepository.save(orgUserRelPo);
            }
        }else{
            orgUserRepository.logicDelete(id);
        }

    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteExpertData(Long id) {
        // 当前操作用户的机构
        Long orgId = OrgAccountHelper.getOrgId();
        if(orgId != null){
            QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
            // 更新用户机构关系
            Predicate predicate = qOrgUserRelPo.id.isNotNull().and(qOrgUserRelPo.org.id.eq(orgId)).and(qOrgUserRelPo.user.id.eq(id));
            OrgUserRelPo orgUserRelPo = orgUserRelRepository.findOne(predicate).orElse(null);
            if(orgUserRelPo != null){
                orgUserRelPo.setExpert(false);
                orgUserRelRepository.save(orgUserRelPo);
            }
        }else{
            orgUserRepository.logicDelete(id);
        }

    }

    @Override
    public void deleteExpertRel(Long id) {
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        Predicate predicate = qOrgUserRelPo.id.isNotNull()
                .and(qOrgUserRelPo.user.id.eq(id))
                .and(qOrgUserRelPo.org.id.eq(OrgAccountHelper.getOrgId()));
        orgUserRelRepository.findOne(predicate).ifPresent(orgUserRelPo -> orgUserRelRepository.delete(orgUserRelPo));
    }

    /**
     * 平台端新增机构用户
     * @param dto
     * @throws PhoneNumberExistedException
     */
    @Override
    public void platCreateOrgUser(OrgUserParamsDto dto) throws PhoneNumberExistedException {
        //查询改用户是否已经存在用户表中
        OrgUserPo phoneOrgUserPo = readOneByPhoneNumber(dto.getPhoneNumber());
        OrgUserPo emailOrgUserPo = readOneByMail(dto.getMail());
        if(phoneOrgUserPo != null){
            throw new PhoneNumberExistedException("手机号码已存在!");
        }else if(emailOrgUserPo != null){
            throw new PhoneNumberExistedException("邮箱已存在!");
        }else{
            if(!ObjectUtil.isEmpty(dto.getPassword())){
                dto.setPassword(AESUtil.encryptPassword(dto.getPassword()));
            }
            OrgUserPo orgUserPo = orgUserRepository.save(orgUserMapper.dto2po(dto));
            //新增与机构的对应关系 TODO 修改成跟部门的关系
//            OrgDeptPo orgDeptPo = orgDeptRepository.getOne(dto.getDeptId());
//            if(orgDeptPo.isItIsOrg() && orgDeptPo.getOrg() != null){
//                //专家信息存在 但是不在本机构下
//                OrgUserRelPo orgUserRelPo = new OrgUserRelPo();
//                orgUserRelPo.setFullTime(false);
//                orgUserRelPo.setExpert(false);
//                orgUserRelPo.setMgr(true);
//                orgUserRelPo.setOrg(orgDeptPo);
//                orgUserRelPo.setUser(orgUserPo);
//                orgUserRelRepository.save(orgUserRelPo);
//            }
        }
    }
    /**
     * 平台端修改机构用户
     * @param dto
     * @throws PhoneNumberExistedException
     */
    @Override
    public void platUpdateOrgUser(OrgUserParamsDto dto) throws PhoneNumberExistedException {
        //查询改用户是否已经存在用户表中
        OrgUserPo orgUserPo = orgUserRepository.getOne(dto.getId());
        orgUserPo.setPhoneNumber(dto.getPhoneNumber());
        orgUserPo.setRealName(RegularExpressionUtil.filterSpace(dto.getRealName()));
        orgUserPo.setMail(dto.getMail());
        if(!StringUtils.isEmpty(dto.getPassword())){
//                orgUserPo.setPassword(md5PasswordHelper.md5Encrypt(dto.getPassword()));
            orgUserPo.setPassword(AESUtil.encryptPassword(dto.getPassword()));
            orgUsernamePasswordRealm.clearCachedAuthenticationInfo(dto.getPhoneNumber());
        }
        orgUserRepository.save(orgUserPo);
    }

    @Override
    public void create(OrgUserParamsDto dto) throws PhoneNumberExistedException {
//        Long orgId = dto.getOrgId();
        dto.setPassword(AESUtil.encryptPassword(AESUtil.DEFAULT_PASSWORD));

        OrgUserPo orgUserPo = new OrgUserPo();
        OrgUserRelPo orgUserRelPo = new OrgUserRelPo();
        // 设置部门
        OrgDeptPo orgDeptPo = orgDeptRepository.findById(dto.getDeptId()).orElse(null);
        if (null != orgDeptPo) {
            if (dto.isType()) {
                orgUserPo = orgUserMapper.dto2po(dto);
                // 如果是新增--前台根据手机号查数据id----
                if(!StringUtils.isEmpty(dto.getId())){
                    QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
                    Predicate predicate = qOrgUserRelPo.id.isNotNull().and(qOrgUserRelPo.user.id.eq(dto.getId())
                            .and(qOrgUserRelPo.org.id.eq(orgDeptPo.getId())));
                    orgUserRelPo = orgUserRelRepository.findOne(predicate).orElse(null);
                    //判断该手机号是否在当前机构下，且设置过了部门
                    if (orgUserRelPo != null) {
                        if(!CollectionUtils.isEmpty(orgUserPo.getDepts())) {
                            throw new PhoneNumberExistedException("手机号码在该机构下已存在!");
                        }
                    }else{
                        //专家信息存在 但是不在本机构下
                        orgUserRelPo = new OrgUserRelPo();
                        orgUserRelPo.setFullTime(false);
                        orgUserRelPo.setExpert(false);
                    }
                }
            } else {
                orgUserPo = readOneByPhoneNumber(dto.getPhoneNumber());
                orgUserPo.setPassword(dto.getPassword());
            }
            orgUserRelPo.setMgr(true);
            List<OrgDeptPo> depts = orgUserPo.getDepts();
            if (null == depts) {
                List<OrgDeptPo> tempDepts = new ArrayList<>();
                tempDepts.add(orgDeptPo);
                orgUserPo.setDepts(tempDepts);
            } else {
                orgUserPo.getDepts().add(orgDeptPo);
            }
            // 设置机构
//            OrgPo orgPo = orgRepository.findById(orgId).orElse(null);
//            OrgDeptPo orgDeptPo = orgDeptService.getOne(orgId);
            orgUserRelPo.setOrg(orgDeptPo);
            orgUserRelPo.setUser(orgUserPo);
            if (null != orgUserPo.getExpertInfo()) {
                orgExpertInfoRepository.save(orgUserPo.getExpertInfo());
            }
            Long[] roleIds = dto.getRoleIds();
            if(roleIds != null && roleIds.length > 0){
                if(!CollectionUtils.isEmpty(orgUserPo.getRoles())){
                    orgUserPo.getRoles().clear();
                }
                Set<OrgRolePo> roles = new HashSet<>();
                for (Long roleId : roleIds) {
                    OrgRolePo orgRolePo = orgRoleRepository.getOne(roleId);
                    roles.add(orgRolePo);
                }
                orgUserPo.setRoles(roles);
            }
            orgUserRepository.save(orgUserPo);
            orgUserRelRepository.save(orgUserRelPo);
        } else {
            orgUserPo = orgUserMapper.dto2po(dto);
            // 设置部门
            List<OrgDeptPo> depts = orgUserPo.getDepts();
            if (null == depts) {
                List<OrgDeptPo> tempDepts = new ArrayList<>();
                tempDepts.add(orgDeptPo);
                orgUserPo.setDepts(tempDepts);
            } else {
                orgUserPo.getDepts().add(orgDeptPo);
            }
            Long[] roleIds = dto.getRoleIds();
            if(roleIds != null && roleIds.length > 0){
                if(!CollectionUtils.isEmpty(orgUserPo.getRoles())){
                    orgUserPo.getRoles().clear();
                }
                Set<OrgRolePo> roles = new HashSet<>();
                for (Long roleId : roleIds) {
                    OrgRolePo orgRolePo = orgRoleRepository.getOne(roleId);
                    roles.add(orgRolePo);
                }
                orgUserPo.setRoles(roles);
            }
            orgUserRepository.save(orgUserPo);
        }
    }

    @Override
    public void update(OrgUserParamsDto dto) throws PhoneNumberExistedException {
        Long orgId = dto.getOrgId();
        OrgUserPo orgUserPo = orgUserRepository.findById(dto.getId()).orElse(null);
        if (null != orgUserPo) {
            if (phoneNumberExisted(dto.getPhoneNumber(), dto.getId(), orgId)) {
                throw new PhoneNumberExistedException("手机号码在该机构下已存在!");
            }
            orgUserMapper.updatePoFromDto(dto, orgUserPo);

            if(!ObjectUtil.isEmpty(dto.getPassword())){
                orgUserPo.setPassword(AESUtil.encryptPassword(dto.getPassword()));
            }

            if(!ObjectUtil.isEmpty(dto.getDeptId())){
                OrgDeptPo orgDeptPo = orgDeptRepository.findById(dto.getDeptId()).orElse(null);
                orgUserPo.getDepts().clear();
                orgUserPo.getDepts().add(orgDeptPo);
            }

            Long[] roleIds = dto.getRoleIds();
            if(roleIds != null && roleIds.length > 0){
                orgUserPo.getRoles().clear();
                Set<OrgRolePo> roles = new HashSet<>();
                for (Long roleId : roleIds) {
                    OrgRolePo orgRolePo = orgRoleRepository.getOne(roleId);
                    roles.add(orgRolePo);
                }
                orgUserPo.setRoles(roles);
            }
//            if (null != dto.getDeptId()) {
//                OrgDeptPo orgDeptPo = orgDeptRepository.findById(dto.getDeptId()).orElse(null);
//                if (null != orgId) {
//                    if (orgDeptPo != null) {
//                        if (!orgUserPo.getDepts().contains(orgDeptPo)) {
//                            // 如果部门在原先列表中不存在,则移除原先该用户在该机构下部门,更换为新部门
//                            QOrgDeptPo qOrgDeptPo = QOrgDeptPo.orgDeptPo;
//                            Predicate predicate = qOrgDeptPo.id.isNotNull()
//                                    .and(qOrgDeptPo.org.id.eq(orgId))
//                                    .and(qOrgDeptPo.users.any().id.eq(dto.getId()));
//                            OrgDeptPo oldDeptPo = orgDeptRepository.findOne(predicate).orElse(null);
//                            orgUserPo.getDepts().remove(oldDeptPo);
//                            orgUserPo.getDepts().add(orgDeptPo);
//                        }
//                    }
//                    OrgExpertInfoParamsDto expertInfo = dto.getExpertInfo();
//                    if (expertInfo != null) {
//                        orgExpertInfoRepository.save(orgUserPo.getExpertInfo());
//                        if (null != expertInfo.getFullTime()) {
//                            QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
//                            Predicate predicate = qOrgUserRelPo.id.isNotNull()
//                                    .and(qOrgUserRelPo.user.id.eq(dto.getId()))
//                                    .and(qOrgUserRelPo.org.id.eq(OrgAccountHelper.getOrgId()));
//                            OrgUserRelPo orgUserRelPo = orgUserRelRepository.findOne(predicate).orElse(null);
//                            if (orgUserRelPo != null) {
//                                orgUserRelPo.setFullTime(expertInfo.getFullTime());
//                                orgUserRelPo.setLeader(expertInfo.getLeader());
//                                orgUserRelRepository.save(orgUserRelPo);
//                            }
//                        }
//                    }
//                }
//            }
            orgUserRepository.save(orgUserPo);
        }
    }

    @Override
    public void updateInfo(OrgUserParamsDto dto) {

//        OrgUserPo orgUserPo = orgUserMapper.dto2po(dto);
//
//        orgExpertInfoRepository.save(orgUserPo.getExpertInfo());
//        orgUserRepository.save(orgUserPo);
//
        OrgUserPo orgUserPo = orgUserRepository.findById(dto.getId()).orElse(   null);
        orgUserMapper.updatePoFromDto(dto, orgUserPo);
        orgExpertInfoRepository.save(orgUserPo.getExpertInfo());
        orgUserRepository.save(orgUserPo);
    }

    @Override
    public void updateInfoByPhoneNumber(OrgUserParamsDto dto) {

        OrgUserPo orgUserPo = orgUserRepository.findByPhoneNumberAndDeletedIsFalse(dto.getPhoneNumber());
        orgUserMapper.updatePoFromDto(dto, orgUserPo);
        orgExpertInfoRepository.save(orgUserPo.getExpertInfo());
        orgUserRepository.save(orgUserPo);
    }

    @Override
    public List<OrgUserPo> readAll(OrgUserParamsDto searchParamsDto) {
        QOrgUserPo qOrgUserPo = QOrgUserPo.orgUserPo;
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        Predicate predicate = qOrgUserPo.id.isNotNull();
        String phoneNumber = searchParamsDto.getPhoneNumber();
        if (!StringUtils.isEmpty(phoneNumber)) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.phoneNumber.like("%" + phoneNumber + "%"));
            // 排序
            Sort sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createdDate"));
            return Lists.newArrayList(orgUserRepository.findAll(predicate, sort));
        }
        Long orgId = searchParamsDto.getOrgId();
        if (orgId != null) {
            return jpaQueryFactory.select(qOrgUserRelPo.user).from(qOrgUserRelPo).where(qOrgUserRelPo.org.id.eq(orgId).and(qOrgUserRelPo.mgr.isTrue())).fetch();
        }
        return null;
    }

    @Override
    public Page<OrgUserPo> readAllByPage(OrgUserParamsDto searchParamsDto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
        QOrgUserPo qOrgUserPo = QOrgUserPo.orgUserPo;

        // 开启谓语查询条件
        Predicate predicate = qOrgUserPo.id.isNotNull()
                .and(qOrgUserPo.deleted.isFalse());

//        //只过滤管理员角色的用户
//        predicate = ExpressionUtils.and(predicate, qOrgUserPo.orgUserRel.any().mgr.isTrue());

        // 携带组织机构时,说明需要查询组织机构下专家列表
//        if (null != OrgAccountHelper.getOrgId()) {
//            predicate = ExpressionUtils.and(predicate, qOrgUserPo.orgUserRel.any().org.id.eq(OrgAccountHelper.getOrgId()));
//        }

        if (null != searchParamsDto.getOrgId()) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.orgUserRel.any().org.id.eq(searchParamsDto.getOrgId()));
        }

        if (!CollectionUtils.isEmpty(searchParamsDto.getOrgIdList())) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.orgUserRel.any().org.id.in(searchParamsDto.getOrgIdList()));
        }

        if (searchParamsDto.isExpert()) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.orgUserRel.any().expert.isTrue());
        }

        if (null != searchParamsDto.getDeptId()) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.depts.any().id.eq(searchParamsDto.getDeptId()));
        }

        String phoneNumber = searchParamsDto.getPhoneNumber();
        if (!StringUtils.isEmpty(phoneNumber)) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.phoneNumber.like("%" + phoneNumber + "%"));
        }

        String realName = searchParamsDto.getRealName();
        if (!StringUtils.isEmpty(realName)) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.realName.like("%" + realName + "%"));
        }

        String unit = searchParamsDto.getUnit();
        if (!StringUtils.isEmpty(unit)) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.unit.like("%" + unit + "%"));
        }

        String researchDomain = searchParamsDto.getExpertInfo() != null ? searchParamsDto.getExpertInfo().getResearchDomain() : "";
        if (!StringUtils.isEmpty(researchDomain)) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.expertInfo.researchDomain.like("%" + researchDomain + "%"));
        }

        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createdDate"));
        }

        // 执行返回
        Pageable pageable = pageParamsDto.getPageableWithSort(sort);

        return orgUserRepository.findAll(predicate, pageable);
    }

    /**
     * 获取全职-非全职专家
     * @param searchParamsDto 查询DTO
     * @param pageParamsDto   分页DTO
     * @param sortParamsDto   排序DTO
     * @return
     */
    @Override
    public Page<OrgUserPo> readAllExpertInfoByPage(OrgUserParamsDto searchParamsDto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
        QOrgUserPo qOrgUserPo = QOrgUserPo.orgUserPo;
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;

        long orgId = searchParamsDto.getOrgId();
        boolean expertFlag = searchParamsDto.isExpert();
        boolean fullTimeFlag = searchParamsDto.getFullTime();
        // 执行返回
        Pageable pageable = pageParamsDto.getPageable();

        // 开启谓语查询条件
        Predicate predicate = qOrgUserPo.id.isNotNull().and(qOrgUserPo.deleted.isFalse());
        String phoneNumber = searchParamsDto.getPhoneNumber();
        if (!StringUtils.isEmpty(phoneNumber)) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.phoneNumber.like("%" + phoneNumber + "%"));
        }

        String realName = searchParamsDto.getRealName();
        if (!StringUtils.isEmpty(realName)) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.realName.like("%" + realName + "%"));
        }

        QueryResults<OrgUserPo> queryResults = jpaQueryFactory.selectFrom(qOrgUserPo)
                .leftJoin(qOrgUserRelPo).on(qOrgUserPo.id.eq(qOrgUserRelPo.user.id))
                .where(qOrgUserRelPo.org.id.eq(orgId).and(qOrgUserRelPo.expert.eq(expertFlag)).and(qOrgUserRelPo.fullTime.eq(fullTimeFlag)))
                .where(predicate)
                .offset(pageable.getPageNumber() * pageable.getPageSize())
                .limit(pageable.getPageSize())
                .fetchResults();

        return  new PageImpl<>(queryResults.getResults(), pageable, queryResults.getTotal());
    }

    @Override
    public void resetPassword(String phoneNumber, String newPassword) {
        orgUserRepository.resetPassword(phoneNumber, AESUtil.encryptPassword(newPassword));
        orgUsernamePasswordRealm.clearCachedAuthenticationInfo(phoneNumber);
    }

    @Override
    public void bindPhoneNumber(Long id, String phoneNumber) throws PhoneNumberExistedException {
        if (phoneNumberExisted(phoneNumber, null, null)) {
            throw new PhoneNumberExistedException("手机号码已存在!");
        }
        orgUserRepository.bindPhoneNumber(id, phoneNumber);
        orgUsernamePasswordRealm.clearCachedAuthenticationInfo(phoneNumber);
        orgSmsRealm.clearCachedAuthenticationInfo(phoneNumber);
    }

    @Override
    public OrgDeptPo readOrgRootDept(Long orgId) {
        QOrgDeptPo qOrgDeptPo = QOrgDeptPo.orgDeptPo;
        Predicate predicate = qOrgDeptPo.id.isNotNull().and(
                qOrgDeptPo.parentId.isNull().and(
                        qOrgDeptPo.id.eq(orgId)
                )
        );
        return orgDeptRepository.findOne(predicate).orElse(null);
    }

    @Override
    @Transactional
    public void setUserRel(OrgUserParamsDto dto) {
        // 获取机构
        OrgPo orgPo = orgRepository.findById(dto.getOrgId()).orElse(null);
        if (orgPo != null) {
            // 设置超级管理人员内容
            OrgUserPo presetMgr = orgUserRepository.findById(dto.getId()).orElse(null);
            if (null != presetMgr) {
                // 设置管理人员
                orgPo.setPresetMgr(presetMgr);
                orgRepository.save(orgPo);
                // 设置超管角色
                // 1.获取机构下的超管角色(创建机构时默认创建)
                QOrgRolePo qOrgRolePo = QOrgRolePo.orgRolePo;
                Predicate predicate = qOrgRolePo.id.isNotNull()
                        .and(qOrgRolePo.orgs.any().id.eq(dto.getOrgId()))
                        .and(qOrgRolePo.preset.isTrue());
                OrgRolePo orgRolePo = orgRoleRepository.findOne(predicate).orElse(null);
                if(orgRolePo != null){
                    // 2.设置用户包含超管角色
                    Set<OrgRolePo> roles = new HashSet<>();
                    roles.add(orgRolePo);
                    presetMgr.setRoles(roles);
                    orgUserRepository.save(presetMgr);
                }
            }
        }

        // 设置关联关系
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        // 判断是否已经存在
        Predicate predicate = qOrgUserRelPo.id.isNotNull()
                .and(qOrgUserRelPo.user.id.eq(dto.getId()))
                .and(qOrgUserRelPo.org.id.eq(dto.getOrgId()));
        OrgUserRelPo result = orgUserRelRepository.findOne(predicate).orElse(null);
        if (result != null) {
            // 如果存在关系,判断是否有管理员角色
            if (!result.isMgr()) {
                result.setMgr(true);
                orgUserRelRepository.save(result);
            }
        } else {
            // 如果不存在关系
            OrgUserRelPo orgUserRelPo = new OrgUserRelPo();
            // 获取用户
            OrgUserPo orgUserPo = orgUserRepository.findById(dto.getId()).orElse(null);
            // 获取根节点部门
            OrgDeptPo orgDeptPo = readOrgRootDept(dto.getOrgId());
            if (orgUserPo != null && orgPo != null) {
                List<OrgDeptPo> depts = orgUserPo.getDepts();
                if (!depts.contains(orgDeptPo)) {
                    orgUserPo.getDepts().add(orgDeptPo);
                }
            }
            orgUserRelPo.setUser(orgUserPo);
            orgUserRelPo.setOrg(orgDeptPo);
            orgUserRelPo.setMgr(true);
            orgUserRelPo.setExpert(false);
            orgUserRelRepository.save(orgUserRelPo);
        }
    }

    @Override
    public OrgUserPo getPresetMgr(Long orgId) {
        QOrgPo qOrgPo = QOrgPo.orgPo;
        Predicate predicate = qOrgPo.id.isNotNull()
                .and(qOrgPo.orgUserRel.any().org.id.eq(orgId));
        OrgPo orgPo = orgRepository.findOne(predicate).orElse(null);
        if (orgPo != null) {
            if (orgPo.getPresetMgr() != null && !orgPo.getPresetMgr().isDeleted()) {
                return orgPo.getPresetMgr();
            }
        }
        return null;
    }

    @Override
    public boolean containsMgr(Long id) {
//        long size = orgUserRelRepository.findIsExsitRole(id);
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        long size = jpaQueryFactory.select(qOrgUserRelPo.id.count()).from(qOrgUserRelPo)
                .where(qOrgUserRelPo.user.id.eq(id).and(qOrgUserRelPo.mgr.isTrue())).fetchCount();
        return size > 0;
    }

    @Override
    public boolean containsExpert(Long id) {
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        long size = jpaQueryFactory.selectFrom(qOrgUserRelPo)
                .where(qOrgUserRelPo.user.id.eq(id).and(qOrgUserRelPo.expert.isTrue())).fetchCount();
//        Predicate predicate = qOrgUserRelPo.user.id.eq(id)
//                .and(qOrgUserRelPo.expert.isTrue());
//        ArrayList<OrgUserRelPo> orgUserRelPos = Lists.newArrayList(orgUserRelRepository.findAll(predicate));
        return size > 0;
    }

    @Override
    public boolean checkFullTime(Long id, OrgUserParamsDto searchDto) {
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        Predicate predicate = qOrgUserRelPo.user.id.eq(id)
                .and(qOrgUserRelPo.org.id.in(searchDto.getOrgIdList()))
                .and(qOrgUserRelPo.fullTime.isTrue());
        return orgUserRelRepository.exists(predicate);
    }

    @Override
    public boolean checkLeader(Long id, OrgUserParamsDto searchDto) {
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        Predicate predicate = qOrgUserRelPo.user.id.eq(id)
                .and(qOrgUserRelPo.org.id.in(searchDto.getOrgIdList()))
                .and(qOrgUserRelPo.leader.isTrue());
        return orgUserRelRepository.exists(predicate);
    }

    @Override
    public Map<String, Object> getAnalyze(Long orgId) {
        Map<String, Object> result = new HashMap<>();
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        Predicate predicate = qOrgUserRelPo.org.id.eq(orgId)
                .and(qOrgUserRelPo.expert.isTrue());
        result.put("allExperts", orgUserRelRepository.count(predicate));
        predicate = qOrgUserRelPo.org.id.eq(orgId)
                .and(qOrgUserRelPo.fullTime.isTrue())
                .and(qOrgUserRelPo.expert.isTrue());
        result.put("fullExperts", orgUserRelRepository.count(predicate));
        predicate = qOrgUserRelPo.org.id.eq(orgId)
                .and(qOrgUserRelPo.fullTime.isFalse())
                .and(qOrgUserRelPo.expert.isTrue());
        result.put("unFullExperts", orgUserRelRepository.count(predicate));
        return result;
    }


    /**
     * 判断手机号码是否在云专家库下存在
     *
     * @param phoneNumber 手机号码
     * @return 执行反馈
     */
    public boolean phoneNumberInDbExisted(String phoneNumber, String realName) {
        QOrgUserPo qOrgUserPo = QOrgUserPo.orgUserPo;
        Predicate predicate = qOrgUserPo.id.isNotNull()
                .and(qOrgUserPo.phoneNumber.eq(phoneNumber))
                .and(qOrgUserPo.realName.eq(realName));
        return orgUserRepository.exists(predicate);
    }

    /**
     * 判断手机号码且是管理员是否在本机构下存在
     *
     * @param phoneNumber 手机号码
     * @param id          用户id
     * @param orgId       机构id
     * @return 执行反馈
     */
    public boolean phoneNumberExisted(String phoneNumber, Long id, Long orgId) {
        QOrgUserPo qOrgUserPo = QOrgUserPo.orgUserPo;
        Predicate predicate = qOrgUserPo.id.isNotNull()
                .and(qOrgUserPo.phoneNumber.eq(phoneNumber))
                .and(qOrgUserPo.deleted.isFalse());
        if(orgId != null){
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.orgUserRel.any().org.id.eq(orgId));
        }
        if (null != id) {
            predicate = ExpressionUtils.and(predicate, qOrgUserPo.id.ne(id));
        }
        return orgUserRepository.exists(predicate);
    }
}
